package org.luxor.commons.workflow.service.impl;

import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.TaskServiceImpl;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.DelegationState;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang.StringUtils;
import org.luxor.commons.core.utils.AssertUtils;
import org.luxor.commons.core.validator.ValidatorUtils;
import org.luxor.commons.workflow.component.cmd.*;
import org.luxor.commons.workflow.constant.TransientVariableConst;
import org.luxor.commons.workflow.constant.VariableConst;
import org.luxor.commons.workflow.entity.*;
import org.luxor.commons.workflow.enums.RejectType;
import org.luxor.commons.workflow.exception.WorkflowServiceException;
import org.luxor.commons.workflow.service.ITaskCoreService;
import org.luxor.commons.workflow.utils.MessageUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 任务管理
 *
 * @author Mr.yan  @date 2021/10/17
 */
@Service
public class TaskCoreServiceImpl implements ITaskCoreService {
    private static final Logger log = LoggerFactory.getLogger(TaskCoreServiceImpl.class);

    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Resource
    private RuntimeService runtimeService;

    /**
     * 待办任务列表
     */
    @Override
    public List<Task> listTodo(TodoTaskQuery query) {
        if (query != null && query.isContainRunToDo() && StringUtils.isBlank(query.getUserId())) {
            throw new WorkflowServiceException("userId 不能为空!");
        }
        TaskQuery taskQuery = taskService.createTaskQuery()
                .orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .active();

        if (StringUtils.isNotBlank(query.getTenantId())) {
            taskQuery.taskTenantId(query.getTenantId());
        }
        if (StringUtils.isNotBlank(query.getTaskName())) {
            taskQuery.taskNameLike("%" + query.getTaskName() + "%");
        }
        if (StringUtils.isNotBlank(query.getCategory())) {
            taskQuery.taskCategory(query.getCategory());
        }

        if (query.getStartTime() != null) {
            taskQuery.taskCreatedAfter(query.getStartTime());
        }
        if (query.getEndTime() != null) {
            taskQuery.taskCreatedBefore(query.getEndTime());
        }
        if (query.isContainRunToDo()) {
            taskQuery.taskCandidateOrAssigned(query.getUserId(), query.getUsersGroups());
        } else {
            if (StringUtils.isNotBlank(query.getUserId()) && !CollectionUtils.isEmpty(query.getUsersGroups())) {
                taskQuery.or().taskCandidateUser(query.getUserId()).taskCandidateGroupIn(query.getUsersGroups()).endOr();
            } else if (StringUtils.isNotBlank(query.getUserId())) {
                taskQuery.taskCandidateUser(query.getUserId());
            } else if (!CollectionUtils.isEmpty(query.getUsersGroups())) {
                taskQuery.taskCandidateGroupIn(query.getUsersGroups());
            }
        }
        int firstResult = (query.getCurrent() - 1) * query.getSize();
        return taskQuery.listPage(firstResult, query.getSize());
    }

    /**
     * 在办任务列表
     */
    @Override
    public List<Task> listRun(RunTaskQuery query) {
        if (query != null && StringUtils.isBlank(query.getUserId())) {
            throw new WorkflowServiceException("userId 不能为空!");
        }
        TaskQuery taskQuery = taskService.createTaskQuery()
                .orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .taskAssignee(query.getUserId())
                .active();
        if (StringUtils.isNotBlank(query.getTaskName())) {
            taskQuery.taskNameLike("%" + query.getTaskName() + "%");
        }
        if (StringUtils.isNotBlank(query.getCategory())) {
            taskQuery.taskCategory(query.getCategory());
        }
        if (query.getStartTime() != null) {
            taskQuery.taskCreatedAfter(query.getStartTime());
        }
        if (query.getEndTime() != null) {
            taskQuery.taskCreatedBefore(query.getEndTime());
        }
        int firstResult = (query.getCurrent() - 1) * query.getSize();
        return taskQuery.listPage(firstResult, query.getSize());
    }

    /**
     * 已办任务列表
     */
    @Override
    public List<HistoricTaskInstance> listDone(DoneTaskQuery query) {
        if (query != null && StringUtils.isBlank(query.getUserId())) {
            throw new WorkflowServiceException("userId 不能为空!");
        }
        HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery()
                .orderByTaskPriority().desc()
                .orderByTaskCreateTime().asc()
                .taskAssignee(query.getUserId())
                .finished();
        if (StringUtils.isNotBlank(query.getTaskName())) {
            taskQuery.taskNameLike("%" + query.getTaskName() + "%");
        }
        if (StringUtils.isNotBlank(query.getCategory())) {
            taskQuery.taskCategory(query.getCategory());
        }
        if (query.getStartTime() != null) {
            taskQuery.taskCreatedAfter(query.getStartTime());
        }
        if (query.getEndTime() != null) {
            taskQuery.taskCreatedBefore(query.getEndTime());
        }
        int firstResult = (query.getCurrent() - 1) * query.getSize();
        return taskQuery.listPage(firstResult, query.getSize());
    }

    public List<Comment> getProcessInstanceComments(String processInstanceId) {
        List<Comment> comments = taskService.getProcessInstanceComments(processInstanceId);
        return comments;
    }

    /**
     * 领取
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void claim(String taskId, String userId) {
        taskService.claim(taskId, userId);
    }

    /**
     * 取消领取
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unClaim(String taskId) {
        taskService.unclaim(taskId);
    }

    /**
     * 完成办理
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void complete(CompleteTask completeTask) {
        ValidatorUtils.validateEntity(completeTask);
        Task currentTask = taskService.createTaskQuery().taskId(completeTask.getTaskId()).singleResult();
        if (currentTask == null) {
            log.warn("任务不存在. taskId:{}", completeTask.getTaskId());
            return;
        }
        if (StringUtils.isNotBlank(completeTask.getUserId()) && StringUtils.isBlank(currentTask.getAssignee())) {
            taskService.claim(currentTask.getId(), completeTask.getUserId());
        }

        // 添加操作记录
        Authentication.setAuthenticatedUserId(completeTask.getUserId());
        String message = MessageUtils.action("同意", completeTask.getReason());
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

        // 办理决策
        completeTask.addTransientVariable(TransientVariableConst.AGREE, completeTask.getAgree());

        // 是待解决的委托任务?
        if (DelegationState.PENDING.equals(currentTask.getDelegationState())) {
            taskService.resolveTask(currentTask.getId(), completeTask.getVariables(), completeTask.getTransientVariables());
        } else {
            taskService.complete(currentTask.getId(), completeTask.getVariables(), completeTask.getTransientVariables());
        }
    }

    /**
     * 指派
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void assign(AssignTask assignTask) {
        ValidatorUtils.validateEntity(assignTask);
        Task currentTask = taskService.createTaskQuery().taskId(assignTask.getTaskId()).singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已撤销或不存在.", Task.class);
        }
        if (StringUtils.isBlank(assignTask.getAssignee()) && assignTask.getCandidate().getUsers().isEmpty()) {
            throw new ActivitiIllegalArgumentException("指派目标任务'候选人'和'办理人'，必须有一个不为空");
        }
        if (currentTask.getDelegationState() != null && currentTask.getDelegationState().equals(DelegationState.PENDING)) {
            throw new ActivitiException("委派的任务不能指派，而应该被解决。");
        }
        if (StringUtils.isNotBlank(assignTask.getUserId()) && StringUtils.isBlank(currentTask.getAssignee())) {
            taskService.claim(currentTask.getId(), assignTask.getUserId());
        }

        // 添加操作记录
        Authentication.setAuthenticatedUserId(assignTask.getUserId());
        String message = MessageUtils.action("同意", assignTask.getReason());
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

        // 分配目标任务-受理人
        assignTask.addTransientVariable(TransientVariableConst.ASSIGNEE, assignTask.getAssignee());
        // 分配目标任务-候选人
        assignTask.addTransientVariable(TransientVariableConst.CANDIDATE_USER_LIST, assignTask.getCandidate().getUsers());
        // 分配目标任务-候选组
        assignTask.addTransientVariable(TransientVariableConst.CANDIDATE_GROUP_LIST, assignTask.getCandidate().getGroups());
        // 分配目标多实例参数
        assignTask.addVariable(VariableConst.ASSIGNEE_LIST, assignTask.getCandidate().getUsers());
        // 分配目标任务-到期时间
        assignTask.addTransientVariable(TransientVariableConst.DUE_DATE, assignTask.getDueDate());
        // 分配目标任务-优先级
        assignTask.addTransientVariable(TransientVariableConst.PRIORITY, assignTask.getPriority());
        // 办理决策
        assignTask.addTransientVariable(TransientVariableConst.AGREE, assignTask.getAgree());

        // 有指定目标活动节点？
        if (StringUtils.isNotBlank(assignTask.getTargetActivityId())) {
            String taskId = currentTask.getId();
            String targetActivityId = assignTask.getTargetActivityId();
            Map<String, Object> variables = assignTask.getVariables();
            Map<String, Object> transientVariables = assignTask.getTransientVariables();
            JumpAnyWhereCmd cmd = new JumpAnyWhereCmd(taskId, targetActivityId, variables, transientVariables);
            ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
        } else {
            for (String userId : assignTask.getCandidate().getUsers()) {
                taskService.addCandidateUser(currentTask.getId(), userId);
            }
            for (String groupId : assignTask.getCandidate().getGroups()) {
                taskService.addCandidateGroup(currentTask.getId(), groupId);
            }
            taskService.complete(currentTask.getId(), assignTask.getVariables(), assignTask.getTransientVariables());
        }
    }

    /**
     * 转办
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void turnTodo(TurnTodoTask turnTodoTask) {
        ValidatorUtils.validateEntity(turnTodoTask);
        Task currentTask = taskService.createTaskQuery().taskId(turnTodoTask.getTaskId()).active().singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已撤销或不存在.", Task.class);
        }
        if (currentTask.getDelegationState() != null && currentTask.getDelegationState().equals(DelegationState.PENDING)) {
            throw new ActivitiException("委派的任务不能转办，而应该被解决。");
        }
        // 指定新的任务受理人
        taskService.unclaim(currentTask.getId());
        if (StringUtils.isNotBlank(turnTodoTask.getAssignee())) {
            taskService.claim(currentTask.getId(), turnTodoTask.getAssignee());
        }

        // 设置委托人
        String owner = StringUtils.isBlank(turnTodoTask.getUserId()) ? currentTask.getAssignee() : turnTodoTask.getUserId();
        taskService.setOwner(turnTodoTask.getTaskId(), owner);

        // 添加操作记录
        Authentication.setAuthenticatedUserId(owner);
        String message = MessageUtils.action("转办", turnTodoTask.getReason());
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

        // 指定新的任务候选人
        Candidate candidate = turnTodoTask.getCandidate();
        for (String userId : candidate.getUsers()) {
            taskService.addCandidateUser(currentTask.getId(), userId);
        }
        // 指定新的任务候选组
        for (String groupId : candidate.getGroups()) {
            taskService.addCandidateGroup(currentTask.getId(), groupId);
        }
        // 设置到期时间
        if (turnTodoTask.getDueDate() != null) {
            taskService.setDueDate(currentTask.getId(), turnTodoTask.getDueDate());
        }
        // 设置优先级
        if (turnTodoTask.getPriority() != null) {
            taskService.setPriority(currentTask.getId(), turnTodoTask.getPriority());
        }
    }

    /**
     * 委托
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delegate(DelegateTask delegateTask) {
        ValidatorUtils.validateEntity(delegateTask);
        Task currentTask = taskService.createTaskQuery().taskId(delegateTask.getTaskId()).active().singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已撤销或不存在.", Task.class);
        }
        // 是委派任务？
        if (currentTask.getDelegationState() != null) {
            throw new ActivitiException("委托办理状态的任务，不能进行二次委派!");
        }
        if (StringUtils.isNotBlank(delegateTask.getUserId()) && StringUtils.isBlank(currentTask.getAssignee())) {
            taskService.claim(currentTask.getId(), delegateTask.getUserId());
        }

        // 添加操作记录
        Authentication.setAuthenticatedUserId(delegateTask.getUserId());
        String message = MessageUtils.action("委派", delegateTask.getReason());
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

        // 委派
        taskService.delegateTask(currentTask.getId(), delegateTask.getAssignee());
    }

    /**
     * 驳回
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reject(RejectTask rejectTask) {
        ValidatorUtils.validateEntity(rejectTask);
        Task currentTask = taskService.createTaskQuery().taskId(rejectTask.getTaskId()).active().singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已撤销或不存在.", Task.class);
        }
        if (StringUtils.isNotBlank(rejectTask.getUserId()) && StringUtils.isBlank(currentTask.getAssignee())) {
            taskService.claim(currentTask.getId(), rejectTask.getUserId());
        }

        // 退回到发起人？
        if (RejectType.StartUser.equals(rejectTask.getRejectType())) {
            Authentication.setAuthenticatedUserId(rejectTask.getUserId());
            String message = MessageUtils.action("退回到发起人", rejectTask.getReason());
            taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

            // 获取提单节点
            List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(currentTask.getProcessInstanceId()).activityType("userTask").finished()
                    .orderByHistoricActivityInstanceStartTime().asc().list();
            if (CollectionUtils.isEmpty(historicActivityInstanceList)) {
                throw new ActivitiObjectNotFoundException("找不到流程的提单节点");
            }

            String taskId = currentTask.getId();
            String targetAssignee = historicActivityInstanceList.get(0).getAssignee();
            String targetActivityId = historicActivityInstanceList.get(0).getActivityId();
            Boolean quickReturn = rejectTask.getQuickReturn();
            HashMap<String, Object> transientVariables = new HashMap<>(3);
            HashMap<String, Object> variables = new HashMap<>(3);
            transientVariables.put(TransientVariableConst.ASSIGNEE, targetAssignee);

            JumpAnyWhereCmd cmd = new JumpAnyWhereCmd(taskId, targetActivityId, quickReturn, variables, transientVariables);
            ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
            return;
        }

        // 驳回到上一步？
        if (RejectType.PrevActivity.equals(rejectTask.getRejectType())) {
            Authentication.setAuthenticatedUserId(rejectTask.getUserId());
            String message = MessageUtils.action("退回到上一步", rejectTask.getReason());
            taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

            if (rejectTask.getQuickReturn()) {
                log.warn("驳回到上一步，不支持[quickReturn]参数");
            }

            String taskId = currentTask.getId();
            RejectPrevNodeCmd cmd = new RejectPrevNodeCmd(taskId);
            ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
            return;
        }

        // 驳回到上个办理人?
        if (RejectType.PrevAssignee.equals(rejectTask.getRejectType())) {
            Authentication.setAuthenticatedUserId(rejectTask.getUserId());
            String message = MessageUtils.action("退回到上个办理人", rejectTask.getReason());
            taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

            if (rejectTask.getQuickReturn()) {
                log.warn("驳回到上个办理人，不支持[quickReturn]参数");
            }

            RejectPrevUserCmd cmd = new RejectPrevUserCmd(currentTask.getId());
            ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
            return;
        }

        // 终止流程?
        if (RejectType.ProcessEnd.equals(rejectTask.getRejectType())) {
            Authentication.setAuthenticatedUserId(rejectTask.getUserId());
            String message = MessageUtils.action("终止流程", rejectTask.getReason());
            taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

            runtimeService.deleteProcessInstance(currentTask.getProcessInstanceId(), rejectTask.getReason());
            return;
        }

        // 退回到任意节点？
        if (RejectType.AnyActivity.equals(rejectTask.getRejectType())) {
            Authentication.setAuthenticatedUserId(rejectTask.getUserId());
            String message = MessageUtils.action("退回到任意节点", rejectTask.getReason());
            taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

            String targetActivityId = rejectTask.getTargetActivityId();
            AssertUtils.notBlank(targetActivityId, "目标节点ID(targetActivityId)，不能为空");

            List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery()
                    .processInstanceId(currentTask.getProcessInstanceId()).activityType("userTask").finished()
                    .activityId(targetActivityId).list();
            if (CollectionUtils.isEmpty(historicActivityInstanceList)) {
                throw new ActivitiIllegalArgumentException("历史办理记录中，找不到该目标节点");
            }

            String taskId = currentTask.getId();
            String targetAssignee = historicActivityInstanceList.get(0).getAssignee();
            Boolean quickReturn = rejectTask.getQuickReturn();
            HashMap<String, Object> transientVariables = new HashMap<>(3);
            HashMap<String, Object> variables = new HashMap<>(3);
            transientVariables.put(TransientVariableConst.ASSIGNEE, targetAssignee);

            JumpAnyWhereCmd cmd = new JumpAnyWhereCmd(taskId, targetActivityId, quickReturn, variables, transientVariables);
            ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
        }
    }

    /**
     * 撤回
     */
    @Override
    public void revoke(String taskId, String userId, String reason) {
        AssertUtils.notNull(taskId, "任务Id(taskId)，不能为空");
        AssertUtils.notNull(userId, "办理人(userId)，不能为空");

        HistoricTaskInstance doneTask = historyService.createHistoricTaskInstanceQuery()
                .taskId(taskId).finished().singleResult();
        if (doneTask == null) {
            throw new ActivitiObjectNotFoundException("已办任务不存在. taskId:" + taskId, Task.class);
        }

        // 添加操作记录
        Authentication.setAuthenticatedUserId(userId);
        String message = MessageUtils.action("撤回", reason);
        taskService.addComment(null, doneTask.getProcessInstanceId(), message);
        ((TaskServiceImpl) taskService).getCommandExecutor().execute(new RevokeTaskCmd(taskId, userId));
    }


    /**
     * 多实例任务-加签
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addMultiInstanceExecution(AddMultiInstanceExecution addMultiInstanceExecution) {
        ValidatorUtils.validateEntity(addMultiInstanceExecution);
        Task currentTask = taskService.createTaskQuery().taskId(addMultiInstanceExecution.getTaskId()).active().singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已撤销或不存在. taskId:" + addMultiInstanceExecution.getTaskId(), Task.class);
        }
        String taskId = currentTask.getId();
        String assignee = addMultiInstanceExecution.getAssignee();
        String reason = addMultiInstanceExecution.getReason();
        boolean beforeMultiInstance = addMultiInstanceExecution.getBeforeInstance();

        // 添加操作记录
        Authentication.setAuthenticatedUserId(currentTask.getAssignee());
        String message = MessageUtils.action("多实例加签", reason);
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);
        ((TaskServiceImpl) taskService).getCommandExecutor().execute(new AddMultiInstanceExecutionCmd(taskId, assignee, beforeMultiInstance));
    }

    /**
     * 多实例任务-减签
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMultiInstanceExecution(DeleteMultiInstanceExecution deleteMultiInstanceExecution) {
        ValidatorUtils.validateEntity(deleteMultiInstanceExecution);

        Task currentTask = taskService.createTaskQuery().taskId(deleteMultiInstanceExecution.getTaskId()).active().singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已办理或不存在. taskId:" + deleteMultiInstanceExecution.getTaskId(), Task.class);
        }

        // 操作人
        Authentication.setAuthenticatedUserId(currentTask.getAssignee());
        String reason = deleteMultiInstanceExecution.getReason();
        boolean executionIsCompleted = deleteMultiInstanceExecution.getExecutionIsCompleted();

        // 添加操作记录
        String message = MessageUtils.action("多实例减签", reason);
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

        DeleteMultiInstanceExecutionCmd cmd = new DeleteMultiInstanceExecutionCmd(currentTask.getId(), executionIsCompleted);
        ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
    }

    /**
     * 普通任务-加(前)签
     *
     * <p>
     * 支持在任意用户节点进行加签，目前存在遗漏问题说明：
     * XXX 1、会导致无法正常获取'流程实例运行情况概览图'
     *
     * @param addTaskInstanceExecution
     * @return void
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addBeforeTaskInstanceExecution(AddTaskInstanceExecution addTaskInstanceExecution) {
        ValidatorUtils.validateEntity(addTaskInstanceExecution);
        Task currentTask = taskService.createTaskQuery().taskId(addTaskInstanceExecution.getTaskId()).active().singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已撤销或不存在. taskId:" + addTaskInstanceExecution.getTaskId(), Task.class);
        }
        String taskId = currentTask.getId();
        String reason = addTaskInstanceExecution.getReason();
        Map<String, Object> variables = addTaskInstanceExecution.getVariables();
        Map<String, Object> transientVariables = addTaskInstanceExecution.getTransientVariables();

        // 添加操作记录
        Authentication.setAuthenticatedUserId(currentTask.getAssignee());
        String message = MessageUtils.action("加前签", reason);
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

        // 设置任务受理人
        String assignee = addTaskInstanceExecution.getAssignee();
        if (StringUtils.isNotBlank(assignee)) {
            transientVariables.put(TransientVariableConst.ASSIGNEE, assignee);
        }
        // 设置任务候选人
        List<String> candidateUserList = addTaskInstanceExecution.getCandidate().getUsers();
        transientVariables.put(TransientVariableConst.CANDIDATE_USER_LIST, candidateUserList);
        // 设置任务候选组
        List<String> candidateGroupList = addTaskInstanceExecution.getCandidate().getGroups();
        transientVariables.put(TransientVariableConst.CANDIDATE_GROUP_LIST, candidateGroupList);
        // 设置到期时间
        if (addTaskInstanceExecution.getDueDate() != null) {
            transientVariables.put(TransientVariableConst.DUE_DATE, addTaskInstanceExecution.getDueDate());
        }
        // 设置优先级
        if (addTaskInstanceExecution.getPriority() != null) {
            transientVariables.put(TransientVariableConst.PRIORITY, addTaskInstanceExecution.getPriority());
        }

        AddBeforeTaskInstanceExecutionCmd cmd = new AddBeforeTaskInstanceExecutionCmd(taskId, variables, transientVariables);
        ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
    }

    /**
     * 普通任务-加(后)签
     *
     * <p>
     * 支持在任意用户节点进行加签，目前存在遗漏问题说明：
     * XXX 1、会导致无法正常获取'流程实例运行情况概览图'
     *
     * @param addTaskInstanceExecution
     * @return void
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addAfterTaskInstanceExecution(AddTaskInstanceExecution addTaskInstanceExecution) {
        ValidatorUtils.validateEntity(addTaskInstanceExecution);
        Task currentTask = taskService.createTaskQuery().taskId(addTaskInstanceExecution.getTaskId()).active().singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已撤销或不存在. taskId:" + addTaskInstanceExecution.getTaskId(), Task.class);
        }
        String taskId = currentTask.getId();
        String reason = addTaskInstanceExecution.getReason();
        Map<String, Object> variables = addTaskInstanceExecution.getVariables();
        Map<String, Object> transientVariables = addTaskInstanceExecution.getTransientVariables();

        // 添加操作记录
        Authentication.setAuthenticatedUserId(currentTask.getAssignee());
        String message = MessageUtils.action("加后签", reason);
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

        // 设置任务受理人
        String assignee = addTaskInstanceExecution.getAssignee();
        if (StringUtils.isNotBlank(assignee)) {
            transientVariables.put(TransientVariableConst.ASSIGNEE, assignee);
        }
        // 设置任务候选人
        List<String> candidateUserList = addTaskInstanceExecution.getCandidate().getUsers();
        transientVariables.put(TransientVariableConst.CANDIDATE_USER_LIST, candidateUserList);
        // 设置任务候选组
        List<String> candidateGroupList = addTaskInstanceExecution.getCandidate().getGroups();
        transientVariables.put(TransientVariableConst.CANDIDATE_GROUP_LIST, candidateGroupList);
        // 设置到期时间
        if (addTaskInstanceExecution.getDueDate() != null) {
            transientVariables.put(TransientVariableConst.DUE_DATE, addTaskInstanceExecution.getDueDate());
        }
        // 设置优先级
        if (addTaskInstanceExecution.getPriority() != null) {
            transientVariables.put(TransientVariableConst.PRIORITY, addTaskInstanceExecution.getPriority());
        }

        AddAfterTaskInstanceExecutionCmd cmd = new AddAfterTaskInstanceExecutionCmd(taskId, variables, transientVariables);
        ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
    }

    /**
     * 自由跳转
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void jump(JumpAnyWhereTask jumpAnyWhereTask) {
        ValidatorUtils.validateEntity(jumpAnyWhereTask);
        Task currentTask = taskService.createTaskQuery().taskId(jumpAnyWhereTask.getTaskId()).active().singleResult();
        if (currentTask == null) {
            throw new ActivitiObjectNotFoundException("任务已撤销或不存在. taskId:" + jumpAnyWhereTask.getTaskId(), Task.class);
        }

        // 添加操作记录
        Authentication.setAuthenticatedUserId(jumpAnyWhereTask.getUserId());
        String message = MessageUtils.action("自由跳转", jumpAnyWhereTask.getReason());
        taskService.addComment(currentTask.getId(), currentTask.getProcessInstanceId(), message);

        String taskId = currentTask.getId();
        String targetActivityId = jumpAnyWhereTask.getTargetActivityId();
        Map<String, Object> variables = jumpAnyWhereTask.getVariables();
        Map<String, Object> transientVariables = jumpAnyWhereTask.getTransientVariables();

        // 设置任务受理人
        String assignee = jumpAnyWhereTask.getAssignee();
        if (StringUtils.isNotBlank(assignee)) {
            transientVariables.put(TransientVariableConst.ASSIGNEE, assignee);
        }
        // 设置任务候选人
        List<String> candidateUserList = jumpAnyWhereTask.getCandidate().getUsers();
        transientVariables.put(TransientVariableConst.CANDIDATE_USER_LIST, candidateUserList);
        // 设置任务候选组
        List<String> candidateGroupList = jumpAnyWhereTask.getCandidate().getGroups();
        transientVariables.put(TransientVariableConst.CANDIDATE_GROUP_LIST, candidateGroupList);
        // 设置多实例参数
        variables.put(VariableConst.ASSIGNEE_LIST, candidateUserList);
        // 设置到期时间
        if (jumpAnyWhereTask.getDueDate() != null) {
            transientVariables.put(TransientVariableConst.DUE_DATE, jumpAnyWhereTask.getDueDate());
        }
        // 设置优先级
        if (jumpAnyWhereTask.getPriority() != null) {
            transientVariables.put(TransientVariableConst.PRIORITY, jumpAnyWhereTask.getPriority());
        }
        //  任务办理后,快速回到当前节点？
        Boolean quickReturn = jumpAnyWhereTask.getQuickReturn();

        JumpAnyWhereCmd cmd = new JumpAnyWhereCmd(taskId, targetActivityId, quickReturn, variables, transientVariables);
        ((TaskServiceImpl) taskService).getCommandExecutor().execute(cmd);
    }

}
